unit SpeechRepeat;

interface

uses
  WaveRecorders, WavePlayers, Classes, lsComponent, XMLIntf, Controls, MPlayer,
  WaveStorage, ExtCtrls;

type
  TOnEndEvent = procedure(ADuration: Integer) of object;

  TSpeechRepeat = class(TlsComponent)
  private
    FDelay: Integer;
    FRecorder: TLiveAudioRecorder;
    FWaveFile: TWaveFile;
    FStartPlay: Boolean;
    FFileName: string;
    FMediaPaly: TMediaPlayer;
    FPlayTimer: TTimer;
    FInRecord: Boolean;
    FPlayWav: Boolean;
    FWaveFileName: string;
    FRecordDelay: Integer;

    procedure ResponsePlayTimer(Sender: TObject);
    procedure ResponsePlayer(Sender: TObject);
    procedure SetDelay(const Value: Integer);
    procedure ResponseRecorderData(Sender: TObject; const Buffer: Pointer;
      BufferSize: Cardinal; var FreeIt: Boolean);
    procedure Start;
    procedure Stop;
  protected
    procedure innerDoAction(AAction: String); override;
  public
    constructor Create(AParent: TWinControl;AlsConfig: IXMLNode); override;
    destructor  Destroy; override;
    procedure SetProperty(ANode: IXMLNode);override;

    property Delay: Integer read FDelay write SetDelay;
  end;

implementation

uses
  Windows, SysUtils, CommonUtils, WaveUtils;

{ TSpeechRepeat }

constructor TSpeechRepeat.Create(AParent: TWinControl;AlsConfig: IXMLNode);
begin
  inherited;

  FPlayTimer := TTimer.Create(nil);
  FPlayTimer.OnTimer := ResponsePlayTimer;
  FPlayTimer.Enabled := False;
  FMediaPaly := TMediaPlayer.Create(nil);
  FMediaPaly.Parent := FParent;
  FMediaPaly.Visible := False;
  FRecorder := TLiveAudioRecorder.Create(nil);
  FRecorder.PCMFormat := Mono16bit8000Hz;

  FRecorder.OnData := ResponseRecorderData;
  FStartPlay := False;
end;

destructor TSpeechRepeat.Destroy;
begin
  FRecorder.OnData := nil;
  FRecorder.Active := False;
  if FWaveFile <> nil then
    FreeAndNil(FWaveFile);
  FreeAndNil(FPlayTimer);
  FreeAndNil(FMediaPaly);
  FreeAndNil(FRecorder);

  inherited;
end;

procedure TSpeechRepeat.innerDoAction(AAction: String);
begin
  inherited;

  if SameText(AAction, 'start') then
    Start
  else if SameText(AAction, 'stop') then
    Stop;
end;


procedure TSpeechRepeat.ResponsePlayer(Sender: TObject);
begin
  if FPlayWav then
    FireEvent('right')
  else begin
    FPlayWav := True;
    FPlayTimer.Interval := Delay;
    FPlayTimer.Enabled := True;
  end;
end;

procedure TSpeechRepeat.ResponsePlayTimer(Sender: TObject);
begin
  if FPlayWav then
  begin
    FPlayTimer.Enabled := False;
    FMediaPaly.FileName := FFileName;
    FMediaPaly.Open;
    FMediaPaly.OnNotify := ResponsePlayer;
    FMediaPaly.Play;
  end
  else if FStartPlay then
  begin
    FStartPlay := False;
    FPlayTimer.Enabled := False;
    FMediaPaly.FileName := FWaveFileName;
    FMediaPaly.Open;
    FMediaPaly.OnNotify := ResponsePlayer;
    FMediaPaly.Play;
  end
  else begin
    FRecorder.Active := False;
    FWaveFile.EndRewrite;
    FWaveFileName := StringReplace(FWaveFileName, 'repeat', 'replay', [rfIgnoreCase]);
    if FileExists(FWaveFileName) then
      DeleteFile(PChar(FWaveFileName));
    FWaveFile.SaveToFile(FWaveFileName);
    FStartPlay := True;
    FPlayTimer.Interval := FDelay;
    FPlayTimer.Enabled := True;
  end;
end;

procedure TSpeechRepeat.ResponseRecorderData(Sender: TObject;
  const Buffer: Pointer; BufferSize: Cardinal; var FreeIt: Boolean);
begin
  FreeIt := True;
  if FStartPlay or FPlayWav then
    Exit;

  if FWaveFile <> nil then
    FWaveFile.Write(Buffer^, BufferSize);
end;

procedure TSpeechRepeat.SetDelay(const Value: Integer);
begin
  FDelay := Value;
end;



procedure TSpeechRepeat.SetProperty(ANode: IXMLNode);
begin
  inherited;

  Delay := GetChildNodeValue(ANode, 'delay');
  FRecordDelay := GetChildNodeValue(ANode, 'recorddelay');
  FFileName := PathOfTrain + GetChildNodeValue(ANode, 'file');
end;

procedure TSpeechRepeat.Start;
begin
  FWaveFileName := GetExePath + 'temp_repeat.wav';
  if FileExists(FWaveFileName) then
    DeleteFile(PChar(FWaveFileName));
  FWaveFile := TWaveFile.Create(FWaveFileName, fmCreate);
  FWaveFile.BeginRewritePCM(FRecorder.PCMFormat);

  FInRecord := False;
  FStartPlay := False;
  FPlayWav := False;
  FRecorder.Active := True;
  FPlayTimer.Interval := FRecordDelay;
  FPlayTimer.Enabled := True;
end;

procedure TSpeechRepeat.Stop;
begin
  FRecorder.Active := False;
  FMediaPaly.Close;
  if FWaveFile <> nil then
    FreeAndNil(FWaveFile);
end;

end.
